home *** CD-ROM | disk | FTP | other *** search
-
- PAGE 60,132
- TITLE 'Step INT 13H Calls'
- NAME STEP13
- ;
- ; ***********************************************************
- ; * *
- ; * S T E P 1 3 *
- ; * *
- ; * Rev 1.0 *
- ; * *
- ; * Nov 20, 1987 *
- ; * *
- ; * Mike Parker *
- ; * 2374 Meadowpark Court *
- ; * Maryland Heights, MO 63043 *
- ; * *
- ; * CIS 70270,161 *
- ; * *
- ; * STEP13 intercepts BIOS INT 13h calls and displays a *
- ; * window that shows the function being called and the *
- ; * parameters being passed to it. Program execution will *
- ; * resume when a key is pressed. This allows you to single *
- ; * step through accesses to the disk at the BIOS level. *
- ; * *
- ; * STEP13 can be activated and de-activated through key- *
- ; * board commands. *
- ; * *
- ; ***********************************************************
- ;
- ;
- ;
- TESTING EQU 0
-
- BG EQU 10H ; BG sets background color (10h = BLUE)
-
- BLACK EQU 00H + BG
- BLUE EQU 01H + BG
- GREEN EQU 02H + BG
- CYAN EQU 03H + BG
- RED EQU 04H + BG
- MAGENTA EQU 05H + BG
- BROWN EQU 06H + BG
- WHITE EQU 07H + BG
- GRAY EQU 08H + BG
- LTBLUE EQU 09H + BG
- LTGREEN EQU 0AH + BG
- LTCYAN EQU 0BH + BG
- LTRED EQU 0CH + BG
- LTMAGENTA EQU 0DH + BG
- YELLOW EQU 0EH + BG
- HIWHITE EQU 0FH + BG
- ;
- CR EQU 13
- LF EQU 10
- BIGR EQU 1352H ; 'R' key
- SMALLR EQU 1372H ; 'r'
- BIGS EQU 1F53H ; 'S' key
- SMALLS EQU 1F73H ; 's'
- ESCAPE EQU 011BH
- HOME EQU 4700H
- UPARROW EQU 4800H
- PGUP EQU 4900H
- LEFTARROW EQU 4B00H
- RIGHTARROW EQU 4D00H
- XEND EQU 4F00H
- DOWNARROW EQU 5000H
- PGDN EQU 5100H
- ;
- BLANK EQU 32
- BRDROW EQU 205
- BRDCOL EQU 186
- ULC EQU 201
- URC EQU 187
- LLC EQU 200
- LRC EQU 188
- ;
- REGBX EQU 00 ; offsets on saved register stack
- REGCX EQU 02
- REGDX EQU 04
- REGDI EQU 06
- REGSI EQU 08
- REGBP EQU 10
- REGES EQU 12
- ;
- ; Format of Step_Flg
- ;
- STOP EQU 01 ; stop and display if bit 0 = 1
- TERM EQU 02 ; terminate STEP13 if bit 1 = 1
- ;
- IF TESTING
- INT13OFF EQU 0e0h*4 ; during testing an unused INT is used
- ELSE
- INT13OFF EQU 13h*4
- ENDIF
-
- INT1cOFF EQU 1ch*4
- INT28OFF EQU 28h*4
-
- Code SEGMENT PUBLIC PARA 'CODE'
-
- ASSUME CS:Code, DS:Code
-
- ORG 100h
-
- Main: ; starting point
- jmp SHORT Main_1
-
- Res_Str db 'STEP13' ; Resident ID string to determine if
- db 0 ; already resident
- ;
- Main_1:
- cli
- cld
- mov AX,CS
- mov SS,AX
- mov SP,OFFSET Pstack
- mov BX,DS ; get difference between segments
- sub AX,BX ; so .EXE file can run during testing
- sti
- ;
- mov BX,OFFSET PRSIZE ; program size in bytes
- mov CL,4
- shr BX,CL ; convert it to paragraphs
- add BX,AX ; add difference between segments
- inc BX ; make it next multiple of 16 bytes
- mov CX,BX ; CX = number paragraphs in this program
- ; offset from PSP base
- ;
- mov BX,002ch
- mov BX,[BX] ; get segment addr of environment from PSP
- ;
- mov AX,CS
- mov DS,AX ; change DS and ES to local area
- mov SegPSP,ES ; save starting segment to release later
- mov ES,AX
- mov SegEnv,BX ; save environment segment to release also
- mov SegEND,CX ; now save CX
- ;
- ; Now that segment registers are all in order see if this program is already
- ; resident by finding out who currently has INT 13h.
- ; Get segment of the program and look for ID string found at start of this
- ; program.
- ;
- push ES
- mov AL,13h
- mov AH,35h
- int 21h ; return address in ES:BX
- call Cmp_Str ; search for ID string
- pop ES
- jnz chkeq ; not found, continue
- ;
- ; This program already installed
- ;
- mov DX,OFFSET ERRmsg
- mov AH,9
- int 21h
- ;
- mov AH,4ch ; terminate (without staying resident)
- mov AL,00
- int 21h
-
- ;
- ; Check equipment list to see if we have graphics or monochrome card
- ;
- chkeq:
- int 11h
- and AX,0030h ; save video mode
- mov BX,0b000h
- cmp AX,0030h ; monochrome?
- jz setcrd
- mov BX,0b800h ; no, graphics card
- setcrd:
- mov Scrseg,BX ; save base segment
- ;
- ; Calculate starting address on screen for window
- ;
- mov BX,OFFSET W1 ; window parameters
- call Window_Parms ; calc start addr of window, wid and ht
- ;
- ; Make room for window save area - AX is number of bytes needed for window
- ;
- mov CL,4
- shr AX,CL ; divide by 16 to get # paragraphs
- inc AX ; handle any remainder
- mov BX,SegPSP ; starting PSP segment
- add BX,SegEND ; size of program in paragraphs
- mov Winseg,BX ; starting segment of window save area
- add SegEND,AX ; expand total space needed by this
- ; programs code and window save area
- ;
- ; Redirect INT 13h, INT 28h and INT 1ch
- ;
- push ES
- cli
- mov AX,0
- mov ES,AX
- mov AX,OFFSET New13
- xchg AX,ES:[INT13OFF]
- mov Save13,AX
- mov AX,CS
- xchg AX,ES:[INT13OFF+2]
- mov Save13+2,AX
-
- IFE TESTING
- mov AX,OFFSET New1c
- xchg AX,ES:[INT1cOFF]
- mov Save1c,AX
- mov AX,CS
- xchg AX,ES:[INT1cOFF+2]
- mov Save1c+2,AX
- ;
- mov AX,OFFSET New28
- xchg AX,ES:[INT28OFF]
- mov Save28,AX
- mov AX,CS
- xchg AX,ES:[INT28OFF+2]
- mov Save28+2,AX
- ENDIF
-
- sti
- pop ES
- ;
- mov DX,OFFSET INITmsg
- mov AH,9
- int 21h
-
- IF TESTING
- mov SP,OFFSET Tstack
- or BYTE PTR CS:Step_Flg,STOP ; set flag to stop and display
-
- include test13.asm
- ;
- mov AH,4ch ; terminate
- mov AL,00
- int 21h
- ELSE
- ;
- ; Terminate and stay resident
- ;
- mov AL,00
- mov AH,31h
- mov DX,SegEND ; segment offset to release free memory
- int 21h ; won't return
- ENDIF
-
- ;
- ; Compare string in program to ID string
- ; Entry:
- ; ES = segment of owning process
- ; DS = current programs segment
- ;
- ; Return:
- ; ZF = 1 if strings equal (TSR already installed)
- ; ZF = 0 if not found
- ;
- Cmp_Str:
- mov SI,OFFSET Res_Str
- mov DI,SI ; source and destination offsets the same
- mov BX,-1 ; assume not found here
- cmp1:
- lodsb
- scasb
- jnz neql
- or AL,AL ; terminating null
- jnz cmp1
- mov BX,0 ; found string
- neql:
- mov AX,BX
- or AX,AX
- ret
-
- ;
- ; Restore vectors and free resident program area.
- ; Interrupts are off upon entry.
- ;
- Restore:
- push AX
- push DS
- push ES
- ;
- mov AX,CS
- mov DS,AX ; load my data segment
- ;
- mov AX,0
- mov ES,AX
- mov AX,Save13 ; restore INT vectors
- mov ES:[INT13OFF],AX
- mov AX,Save13+2
- mov ES:[INT13OFF+2],AX
-
- IFE TESTING
- mov AX,Save28
- mov ES:[INT28OFF],AX
- mov AX,Save28+2
- mov ES:[INT28OFF+2],AX
- ;
- mov AX,Save1c
- mov ES:[INT1cOFF],AX
- mov AX,Save1c+2
- mov ES:[INT1cOFF+2],AX
- ENDIF
-
- ;
- ; Free allocated memory from environment and this program
- ;
- mov ES,SegEnv
- mov AH,49h
- int 21h
- ;
- mov ES,SegPSP ; start of this programs segment
- mov AH,49h
- int 21h
- ;
- pop ES
- pop DS
- pop AX
- ret
-
- ;
- ; INT 1ch will be redirected to here each time a timer tick occurs.
- ; Do keyboard BIOS call to get state of control and shift keys.
- ; If both LEFT and RIGHT shift keys down, enable the Int 13 intercept code.
- ; If CONTROL key and LEFT and RIGHT shift keys down, set the terminate flag.
- ; On the next Int 28h call by DOS, we will remove this program from memory.
- ;
- New1c:
- push AX
- mov AH,02 ; get shift status
- int 16h
- and AL,07 ; save control, left and right shift status
- cmp AL,03 ; are they both down?
- jnz tstctl ; jump if no
- or BYTE PTR CS:Step_Flg,STOP ; set flag to stop and display Int 13h
- tstctl:
- cmp AL,07 ; three keys down?
- jnz n1cout
- or BYTE PTR CS:Step_Flg,TERM ; set terminate flag
- n1cout:
- pop AX
- jmp CS:[DWORD PTR Save1c] ; continue in the chain
-
- ;
- ; The DOS idle loop will be redirected to here.
- ; Check for TERMINATE bit set. If so, free all memory used by this TSR program
- ; and restore all vectors to their original values.
- ;
- New28:
- test BYTE PTR CS:Step_Flg,TERM
- jz n28out
- call Restore
- cli
- n28out:
- jmp CS:[DWORD PTR Save28] ; continue in the chain
-
- ;
- ; INT 13h will be redirected to here
- ;
- New13:
- push AX ; use USERS'S stack for first 3 words
- push DS
- pushf ; push them but we don't need them here
- ;
- cli
- mov AX,CS ; now switch to internal stack
- mov DS,AX
- mov SSsave,SS
- mov SPsave,SP
- mov SS,AX
- mov SP,OFFSET Pstack
- sti
- ;
- push ES
- push BP
- push SI
- push DI
- push DX
- push CX
- push BX
- mov BP,SP ; save base pointer to display reg's
- mov ES,AX
- test BYTE PTR Step_Flg,STOP ; should we stop and display?
- jz norun ; no, restore registers and leave
- ;
- ; Recover registers on USER'S stack
- ;
- push ES
- les BX,Ssave
- mov AX,ES:[BX+2] ; get DS
- mov DSsave,AX
- mov AX,ES:[BX+4] ; get AX
- mov AXsave,AX
- mov Last_FC,AH ; save as last function code
- mov AX,ES:[BX+6] ; get IP
- mov IPsave,AX
- mov AX,ES:[BX+8] ; get CS
- mov CSsave,AX
- mov AX,ES:[BX+10] ; get FLAGS on entry
- mov FLsave,AX
- pop ES
- ;
- cld ; clear direction flag for string operations
- test BYTE PTR Skip_Flg,0ffh ; skip certain functions?
- jz noskip ; no, continue
- mov AX,AXsave ; get USER's AX register with function code
- cmp AH,Skip_Typ ; compare upper half to type to skip
- jz norun ; don't want to break on this one again
- mov BYTE PTR Skip_Flg,00 ; skip flag was set but this is new
- ; function, so break from now on
- noskip:
- call Open_Window
- call Show_Func ; show function number
- call Disp_Text ; display description of BIOS function
- call Show_Help
- ;
- call Get_Key ; wait for a key pressed
- call Disp_Key ; dispatch to key handler
- jc noskip ; if carry set, need to redisplay window
- call Close_Window
- norun:
- pop BX
- pop CX
- pop DX
- pop DI
- pop SI
- pop BP
- pop ES
- cli
- mov SS,SSsave ; switch back to user's stack
- mov SP,SPsave
- ;
- mov AX,FLsave ; get original user's flags before INT 13h
- push AX ; sneak them into flag register
- popf
- ;
- pop AX ; dummy pop to get flags off stack
- pop DS ; restore registers left on user's stack
- pop AX ; now get real AX
-
- IFE TESTING
- pushf
- cli ; give interrupt code IF = 0 like normal
- call CS:[DWORD PTR Save13]
- ENDIF
-
- push AX ; use USERS'S stack for first 3 words
- push DS
- pushf ; they will get used this time
- ;
- cli
- mov AX,CS ; now switch to internal stack
- mov DS,AX
- mov SSsave,SS
- mov SPsave,SP
- mov SS,AX
- mov SP,OFFSET Pstack
- sti
- ;
- push ES
- push BP
- push SI
- push DI
- push DX
- push CX
- push BX
- mov BP,SP ; save base pointer to display reg's
- mov ES,AX
- cld ; clear direction flag for string operations
- ;
- ; Recover registers on USER'S stack
- ;
- push ES
- les BX,Ssave
- mov AX,ES:[BX+0] ; get FLAGS on exit
- mov FLsave,AX
- mov AX,ES:[BX+2] ; get DS
- mov DSsave,AX
- mov AX,ES:[BX+4] ; get AX
- mov AXsave,AX
- mov AX,ES:[BX+6] ; get IP
- mov IPsave,AX
- mov AX,ES:[BX+8] ; get CS
- mov CSsave,AX
- pop ES
- ;
- xor AL,AL
- xchg AL,Ret_Flg ; read value and clear flag for next time
- test AL,0ffh ; is flag set to display return value?
- jz nostop
- ;
- call Open_Window
- call Show_Func ; show function number
- call Disp_Ret ; display return code in AX and flags
- call Get_Key ; wait for a key pressed
- call Close_Window
- nostop:
- pop BX
- pop CX
- pop DX
- pop DI
- pop SI
- pop BP
- pop ES
- cli
- mov SS,SSsave
- mov SP,SPsave
- popf
- pop DS
- pop AX
- retf 2
-
- ;
- ; Display return code in AX, carry and zero flags
- ;
- Disp_Ret:
- mov CX,0301h
- mov DX,OFFSET RCStr
- mov DI,14
- mov AX,AXsave
- call OutWord
- ;
- mov DX,OFFSET CFStr
- mov DI,14
- add DI,DX
- mov AL,'0'
- test FLsave,0001 ; carry flag is least significant bit
- jz dcy
- inc AL ; carry was set so change to '1'
- dcy:
- mov [DI],AL ; store it in string
- add CX,0100h ; move cursor position
- call Disp_Str
- ;
- mov DX,OFFSET ZFStr
- mov DI,14
- add DI,DX
- mov AL,'0'
- test FLsave,0040h ; test zero flag
- jz dzf
- inc AL ; zero was set so change to '1'
- dzf:
- mov [DI],AL ; store it in string
- add CX,0100h ; move cursor position
- call Disp_Str
- ;
- mov CX,0a0ah ; display some help
- mov DX,OFFSET HlpStr5
- mov AH,YELLOW
- call WPrint
- ;
- mov CX,0b0bh ; move cursor position
- mov DX,OFFSET HlpStr6
- mov AH,YELLOW
- call WPrint
- ret
-
- ;
- ; Display function code description in window
- ;
- Show_Func:
- mov CX,0007h ; cursor position - row, col
- mov DX,OFFSET FCStr ; message address
- mov DI,DX
- add DI,19 ; offset this many into string
- mov AL,Last_FC ; get last function code
- call Shexbyt ; convert it to ASCII
- mov BX,OFFSET W1 ; window
- mov AH,YELLOW ; attribute
- call WPrint
- ret
-
- ;
- ; Display input parameters
- ;
- Disp_Parms:
- call Disp_Drv ; show drive number
- call Disp_Head ; head number
- call Disp_Trk ; track number
- call Disp_Sec ; sector number
- ret
-
- ;
- ; Display input parameters for Hard Disk calls
- ; Displays "CYLINDER" instead of "TRACK"
- ;
- Disp_HD_Parms:
- call Disp_Drv
- call Disp_Head
- call Disp_Cyl ; show cylinder number
- ret
-
- ;
- ; Display Drive ID
- ;
- Disp_Drv:
- mov CX,0401h
- mov DX,OFFSET DrvStr
- mov DI,DX
- add DI,8
- mov AX,[BP+REGDX] ; DL register has drive #
- call Shexbyt
- mov AH,HIWHITE
- call WPrint
- ret
-
- ;
- ; Display Head #
- ;
- Disp_Head:
- add CX,0100h
- mov DX,OFFSET HedStr
- mov DI,DX
- add DI,8
- mov AX,[BP+REGDX] ; DH register has head #
- mov AL,AH
- call Sdecbyt
- mov AH,HIWHITE
- call WPrint
- ret
-
- ;
- ; Display Track #
- ;
- Disp_Trk:
- add CX,0100h
- mov DX,OFFSET TrkStr
- mov DI,DX
- add DI,7
- mov AX,[BP+REGCX] ; CH register has track #
- mov AL,AH
- xor AH,AH ; clear upper half
- call HextoDec
- dec SI ; back up to get three chars instead
- movsb ; of normal two
- movsb
- movsb
- mov AH,HIWHITE
- call WPrint
- ret
-
- ;
- ; Display Cylinder #
- ;
- Disp_Cyl:
- add CX,0100h
- mov DX,OFFSET CylStr
- mov DI,DX
- add DI,7
- mov AX,[BP+REGCX] ; CH register has cylinder #
- mov AL,AH
- xor AH,AH ; clear upper half
- call HextoDec
- dec SI
- movsb
- movsb
- movsb
- mov AH,HIWHITE
- call WPrint
- ret
-
- ;
- ; Display Sector #
- ;
- Disp_Sec:
- add CX,0100h
- mov DX,OFFSET SecStr
- mov DI,DX
- add DI,8
- mov AX,[BP+REGCX] ; CL register has sector #
- call Sdecbyt
- mov AH,HIWHITE
- call WPrint
- ret
-
- ;
- ; Display HELP in Window
- ;
- Show_Help:
- mov CX,0a03h ; cursor position - row, col
- mov AH,LTRED ; attribute for char
- mov AL,'S'
- call WChar ; write one character with attribute
- ;
- add CX,0001h ; add 1 to column number
- mov DX,OFFSET HlpStr1 ; message address
- mov AH,WHITE
- call WPrint
- ;
- add CX,0012h ; move column number
- mov AH,LTRED ; attribute for char
- mov AL,'R'
- call WChar ; write one character with attribute
- ;
- add CX,0001h ; move column number
- mov DX,OFFSET HlpStr2
- mov AH,WHITE
- call WPrint
- ;
- mov CX,0b01h ; cursor position - row, col
- mov AH,LTRED
- mov AL,'E'
- call WChar
- ;
- add CX,0001h
- mov AH,LTRED
- mov AL,'S'
- call WChar
- ;
- add CX,0001h
- mov AH,LTRED
- mov AL,'C'
- call WChar
- ;
- add CX,0001h
- mov DX,OFFSET HlpStr3
- mov AH,WHITE
- call WPrint
- ;
- add CX,000dh
- mov AH,LTRED
- mov AL,18h ; up arrow
- call WChar
- ;
- add CX,0001h
- mov AH,LTRED
- mov AL,19h ; down arrow
- call WChar
- ;
- add CX,0001h
- mov AH,LTRED
- mov AL,1bh ; left arrow
- call WChar
- ;
- add CX,0001h
- mov AH,LTRED
- mov AL,1ah ; right arrow
- call WChar
- ;
- add CX,0001h
- mov DX,OFFSET HlpStr4
- mov AH,WHITE
- call WPrint
- ret
-
- ;
- ; HextoDec converts a word in AX to an ASCII string
- ; Entry:
- ; AX = word to convert
- ; Exit:
- ; SI = Pointer to last two character of ASCII string in 'Astr'
- ;
- HextoDec:
- push AX
- push CX
- push DX
- push DI
- ;
- mov DI,OFFSET Astr
- mov CX,10000
- xor DX,DX
- div CX ; num / 10000
- add AL,'0'
- stosb
- mov AX,DX
- mov CX,1000
- xor DX,DX
- div CX ; num / 1000
- add AL,'0'
- stosb
- mov AX,DX
- mov CX,100
- xor DX,DX
- div CX ; num / 100
- add AL,'0'
- stosb
- mov AX,DX
- mov CX,10
- xor DX,DX
- div CX ; num / 10
- add AL,'0'
- stosb
- mov AX,DX
- add AL,'0'
- stosb
- xor AL,AL ; <NULL> terminator in string
- stosb
- sub DI,3 ; back up pointer
- mov SI,DI
- ;
- pop DI
- pop DX
- pop CX
- pop AX
- ret
-
- ;
- ; Display the text description of the current BIOS function code
- ;
- Disp_Text:
- mov CX,LENFC / 6 ; number of entries
- mov AX,AXsave ; get user's function code
- cmp AH,CL ; is it in range?
- jnb not_fnd ; jump if no
- mov DI,OFFSET FCtbl
- cmpdt:
- cmp AH,[DI+1] ; is this the right function?
- jz dtexec
- add DI,6 ; no, point to next
- loop cmpdt
- not_fnd:
- mov DX,OFFSET STRUN
- mov CX,0201h
- call Disp_Str
- ret
-
- dtexec:
- mov CX,0201h ; row, col to position string
- mov DX,[DI+2] ; get pointer to string
- call [WORD PTR DI+4] ; go to display routine
- ret
-
- ;
- ; Display string of DOS function code description
- ;
- ; Entry:
- ; DX = pointer to string
- ; CX = Row, Col
- ;
- Disp_Str:
- mov BX,OFFSET W1
- mov AH,HIWHITE
- call WPrint
- ret
-
- ;
- ; Routines to build string for display - some values need to be filled in
- ; Entry:
- ; DX = pointer to string
- ; CX = Row, Col in window
- ;
- ; Read sectors
- ;
- Disp_02:
- mov DI,5
- add DI,DX
- mov AX,AXsave ; AL has number of sectors to read
- call Sdecbyt ; convert it to ASCII decimal
- call Disp_Str
- call Disp_Parms ; show input parameters
- call Disp_Buf ; show buffer addr in ES:BX
- ret
- ;
- ; Write sectors
- ;
- Disp_03:
- mov DI,6
- add DI,DX
- mov AX,AXsave ; AL has number of sectors to write
- call Sdecbyt ; convert it to ASCII decimal
- call Disp_Str
- call Disp_Parms ; show input parameters
- call Disp_Buf
- ret
-
- ;
- ; Verify sectors
- ;
- Disp_04:
- mov DI,7
- add DI,DX
- mov AX,AXsave ; AL has number of sectors to write
- call Sdecbyt ; convert it to ASCII decimal
- call Disp_Str ; show function description
- call Disp_Parms ; show input parameters
- ret
-
- ;
- ; Format track
- ;
- Disp_05:
- call Disp_Str
- call Disp_Parms
- call Disp_Buf
- ret
-
- ;
- ; Read and Write Long
- ;
- Disp_0a:
- Disp_0b:
- call Disp_Str
- call Disp_HD_Parms ; show Drive, Head and Cylinder
- call Disp_Sec ; show Sector #
- call Disp_Buf ; and Buffer address
- ret
-
- ;
- ; Seek to Cylinder
- ;
- Disp_0c:
- call Disp_Str
- call Disp_HD_Parms ; show Drive, Head and Cylinder
- ret
-
- ;
- ; Alternate Disk Reset
- ;
- Disp_0d:
- call Disp_Str
- call Disp_Drv ; show drive ID
- ret
-
- ;
- ; Test for Drive Ready
- ;
- Disp_10:
- call Disp_Str
- call Disp_Drv
- ret
-
- ;
- ; Recalibrate Drive
- ;
- Disp_11:
- call Disp_Str
- call Disp_Drv
- ret
-
- ;
- ; Get Disk Type
- ;
- Disp_15:
- call Disp_Str
- call Disp_Drv
- ret
-
- ;
- ; Set Disk Type
- ;
- Disp_17:
- mov DI,17
- add DI,DX
- mov AX,AXsave ; AL has disk type
- call Shexbyt
- call Disp_Str
- ;
- mov AX,AXsave
- mov DX,OFFSET Str170
- cmp AL,00 ; no disk?
- jz d17shw
- mov DX,OFFSET Str171
- cmp AL,01 ; regular diskette?
- jz d17shw
- mov DX,OFFSET Str173
- cmp AL,03 ; high capacity diskette?
- jnz d17drv
- d17shw:
- add CX,0100h
- call Disp_Str
- d17drv:
- call Disp_Drv
- ret
-
- ;
- ; Display ES:BX registers
- ;
- Disp_Buf:
- mov DX,OFFSET BufStr ; show buffer address
- mov DI,17
- add CX,0100h
- call OutESBX
- ret
-
- ;
- ; Convert users's ES and BX to ASCII, imbed them in target string
- ; Entry:
- ; DX = pointer to string
- ; DI = offset where to put converted ES:BX
- ; CX = Row, Col
- ;
- OutESBX:
- add DI,DX
- mov AX,[BP+REGES] ; get user's ES
- call Shexwrd
- inc DI ; skip past ':'
- mov AX,[BP+REGBX] ; get user's BX
- call Shexwrd
- call Disp_Str
- ret
-
- ;
- ; Convert word in AX to ASCII, imbed it in target string
- ; Entry:
- ; AX = word to convert
- ; CX = row, col
- ; DX = pointer to string
- ; DI = offset where to put converted AX
- ;
- OutWord:
- add DI,DX
- call Shexwrd
- call Disp_Str
- ret
-
-
- Open_Window:
- push BP
- push ES
- ;
- ; Calculate current page offset each time since it can change at any time
- ;
- mov AH,0fh ; get current video state
- int 10h
- mov CL,BH ; returns BH = active page #
- xor CH,CH
- mov AX,0100h ; page length in paragraphs
- mul cx
- add AX,Scrseg ; add base segment of screen
- mov Pageseg,AX
- ;
- ; Save current contents of window area
- ;
- mov BX,OFFSET W1 ; window parameters
- mov SI,[BX].startmem ; screen addr of start of window
- mov DX,[BX].height
- mov ES,Winseg ; point to allocated memory block
- mov DI,0000
- saverow:
- push DS
- mov CX,[BX].xwidth
- mov DS,Pageseg ; get screen segment
- push SI ; save screen offset
- rep movsw ; do word to get char and attribute
- pop SI
- pop DS
- add SI,BytesPL ; next row down
- dec DX
- jnz saverow
- ;
- ; Draw window
- ;
- mov ES,Pageseg ; get screen segment
- mov DI,[BX].startmem ; physical addr of start of window
- mov AH,HIWHITE
- ;
- ; Draw top border
- ;
- push DI
- mov AL,ULC ; write upper left corner
- stosw
- mov CX,[BX].xwidth
- sub CX,2
- mov AL,BRDROW
- rep stosw
- mov AL,URC ; write upper right corner
- stosw
- pop DI
- add DI,BytesPL ; next row down
- ;
- ; Draw middle of window
- ;
- mov DX,[BX].height
- sub DX,2
- winrows:
- push DI
- mov AL,BRDCOL ; left border column
- stosw
- mov CX,[BX].xwidth
- sub CX,2
- mov AL,BLANK
- rep stosw
- mov AL,BRDCOL ; right border column
- stosw
- pop DI
- add DI,BytesPL ; next row down
- dec DX
- jnz winrows
- ;
- ; Draw bottom border
- ;
- push DI
- mov AL,LLC ; write lower left corner
- stosw
- mov CX,[BX].xwidth
- sub CX,2
- mov AL,BRDROW
- rep stosw
- mov AL,LRC ; write lower right corner
- stosw
- pop DI
- ;
- pop ES
- pop BP
- ret
-
-
- Close_Window:
- push ES
- mov BX,OFFSET W1
- mov DI,[BX].startmem ; physical addr of screen area
- mov ES,Pageseg ; point to allocated memory block
- mov SI,0000 ; start of save memory block
- mov DX,[BX].height
- resrow:
- push DS
- mov CX,[BX].xwidth
- mov DS,Winseg ; get saved memory segment
- push DI ; save screen offset
- rep movsw ; do word to get char and attribute
- pop DI
- pop DS
- add DI,BytesPL ; next row down
- dec DX
- jnz resrow
- pop ES
- ret
-
- ;
- ; Print a string in window.
- ; Entry:
- ; CX = Row, Col position relative to start of window
- ; BX = Window pointer
- ; AH = Attribute
- ; DX = addr of string
- ;
- WPrint:
- push ES
- call GetRC ; convert to row, col in DI
- mov ES,Pageseg
- mov SI,DX ; move string address
- wpwrt:
- cmp BYTE PTR [SI],00 ; test for string terminator <NULL>
- jz wpexit
- lodsb
- stosw
- jmp wpwrt
- wpexit:
- pop ES
- ret
-
- ;
- ; Write one character and attribute to window
- ;
- ; Entry:
- ; CX = Row, Col position relative to start of window
- ; BX = Window pointer
- ; AH = attr
- ; AL = char
- ;
- WChar:
- push ES
- call GetRC ; convert to row, col in DI
- mov ES,Pageseg
- stosw
- pop ES
- ret
-
- ;
- ; Convert row, col in CX to physical addr in DI
- ;
- GetRC:
- push AX
- push DX
- mov DI,[BX].startmem ; physical start of window memory
- add DI,BytesPL ; go down a row
- add DI,2 ; go in one char, this is 0,0
- mov AL,CH
- xor AH,AH ; AX = relative row number
- mul BytesPL ; this clobbers DX
- add DI,AX
- mov AX,CX ; restore coordinates
- xor AH,AH ; AX = relative col number
- shl AX,1 ; times 2 for attribute
- add DI,AX
- pop DX
- pop AX
- ret
-
- ;
- ; STORE HEX WORD
- ; Convert a hex word to ASCII and store it in destination string
- ; Entry:
- ; AX = Word to convert
- ; DI = destination pointer
- ;
- Shexwrd:
- xchg AL,AH ; convert upper half first
- call Shexbyt
- xchg AL,AH ; convert lower half
- call Shexbyt
- ret
-
- ;
- ; STORE HEX BYTE
- ; Convert a hex byte to ASCII and store it in destination string
- ; Entry:
- ; AL = Byte to convert
- ; DI = destination pointer
- ;
- Shexbyt:
- push AX
- mov AH,AL ; save temporarily
- shr AL,1
- shr AL,1
- shr AL,1
- shr AL,1
- cmp AL,10
- jb wh1
- add AL,07
- wh1:
- add AL,'0'
- stosb
- mov AL,AH
- and AL,0fh
- cmp AL,10
- jb wh2
- add AL,07
- wh2:
- add AL,'0'
- stosb
- pop AX
- ret
-
- ;
- ; STORE DECIMAL BYTE
- ; Convert a hex byte to ASCII decimal and store it in destination string
- ; Entry:
- ; AL = Byte to convert
- ; DI = destination pointer
- ;
- Sdecbyt:
- and AX,00ffh ; mask off upper half
- call HextoDec
- movsb ; copy 2 chars to destination string
- movsb
- ret
-
- ;
- ; Check if key pressed requires special handling
- ;
- ; Entry:
- ; AX = key pressed
- ;
- Disp_Key:
- mov DI,OFFSET Keytbl ; keys and subroutine addresses
- mov CX,LENKTAB / 4 ; number of entries
- cmpdk:
- cmp AX,[DI] ; is key in table?
- jz dkexec
- add DI,4 ; no, point to next key value
- loop cmpdk
- clc ; carry clear means exit upon return
- ret
- dkexec:
- add DI,2
- call [WORD PTR DI]
- ret
-
- ;
- ; Table of keys to watch for followed by the address of the routine to execute
- ;
- Keytbl dw ESCAPE, DO_Esc
- dw BIGS, Do_Skey
- dw SMALLS, Do_Skey
- dw BIGR, Do_Rkey
- dw SMALLR, Do_Rkey
- dw UPARROW, Do_Up
- dw DOWNARROW, Do_Down
- dw LEFTARROW, Do_Left
- dw RIGHTARROW, Do_Right
- dw HOME, Do_Home
- dw XEND, Do_End
- dw PGUP, Do_Pgup
- dw PGDN, Do_Pgdn
- LENKTAB EQU $ - Keytbl
-
- ;
- ; If ESC key, clear flag so Int 13h will not be stopped each time
- ;
- Do_Esc:
- and BYTE PTR Step_Flg,255-STOP
- clc ; carry clear means exit upon return
- ret
-
- ;
- ; 'S' key - skip successive functions of current type.
- ; Return to intercepting calls when something new comes along.
- ;
- Do_Skey:
- mov AL,0ffh
- mov Skip_Flg,AL ; set flag to show we should skip something
- mov AL,Last_FC ; get current function code
- mov Skip_Typ,AL ; save it
- clc ; carry clear means exit upon return
- ret
-
- ;
- ; 'R' key - stop after INT 13h call and let user see results
- ;
- Do_Rkey:
- mov AL,0ffh
- mov Ret_Flg,AL ; set flag
- clc ; carry clear means exit upon return
- ret
-
- ;
- ; DO_Up - move window up one line
- ;
- Do_Up:
- mov BX,OFFSET W1
- call Close_Window
- mov AX,[BX].leftrow
- or AX,AX ; already at top of screen?
- jz upexit
- dec [BX].leftrow
- dec [BX].rightrow
- call Window_Parms ; recalculate parameters
- upexit:
- stc ; don't exit upon return
- ret
-
- ;
- ; DO_Down - move window down one line
- ;
- Do_Down:
- mov BX,OFFSET W1
- call Close_Window
- mov AX,[BX].rightrow
- cmp AX,24 ; already at bottom of screen?
- jz dnexit
- inc [BX].leftrow
- inc [BX].rightrow
- call Window_Parms ; recalculate parameters
- dnexit:
- stc ; don't exit upon return
- ret
-
- ;
- ; DO_Left - move window left one column
- ;
- Do_Left:
- mov BX,OFFSET W1
- call Close_Window
- mov AX,[BX].leftcol
- or AX,AX ; already at left of screen?
- jz lfexit
- dec [BX].leftcol
- dec [BX].rightcol
- call Window_Parms ; recalculate parameters
- lfexit:
- stc ; don't exit upon return
- ret
-
- ;
- ; Do_Right - move window right one column
- ;
- Do_Right:
- mov BX,OFFSET W1
- call Close_Window
- mov AX,[BX].rightcol
- cmp AX,79 ; already at right of screen?
- jz rtexit
- inc [BX].leftcol
- inc [BX].rightcol
- call Window_Parms ; recalculate parameters
- rtexit:
- stc ; don't exit upon return
- ret
-
- ;
- ; Do_Home - move window to upper left corner
- ;
- Do_Home:
- mov BX,OFFSET W1
- call Close_Window
- xor AX,AX
- mov [BX].leftrow,AX
- mov [BX].leftcol,AX
- ;
- mov AX,[BX].leftrow
- add AX,[BX].height
- dec AX
- mov [BX].rightrow,AX
- ;
- mov AX,[BX].leftcol
- add AX,[BX].xwidth
- dec AX
- mov [BX].rightcol,AX
- ;
- call Window_Parms ; recalculate parameters
- stc ; don't exit upon return
- ret
-
- ;
- ; Do_End - move window to lower left corner
- ;
- Do_End:
- mov BX,OFFSET W1
- call Close_Window
- mov AX,24
- mov [BX].rightrow,AX
- xor AX,AX
- mov [BX].leftcol,AX
- ;
- mov AX,[BX].rightrow
- sub AX,[BX].height
- inc AX
- mov [BX].leftrow,AX
- ;
- mov AX,[BX].leftcol
- add AX,[BX].xwidth
- dec AX
- mov [BX].rightcol,AX
- ;
- call Window_Parms ; recalculate parameters
- stc ; don't exit upon return
- ret
-
- ;
- ; Do_Pgup - move window to upper right corner
- ;
- Do_Pgup:
- mov BX,OFFSET W1
- call Close_Window
- xor AX,AX
- mov [BX].leftrow,AX
- mov AX,79
- mov [BX].rightcol,AX
- ;
- mov AX,[BX].leftrow
- add AX,[BX].height
- dec AX
- mov [BX].rightrow,AX
- ;
- mov AX,[BX].rightcol
- sub AX,[BX].xwidth
- inc AX
- mov [BX].leftcol,AX
- ;
- call Window_Parms ; recalculate parameters
- stc ; don't exit upon return
- ret
-
- ;
- ; Do_Pgdn - move window to lower right corner
- ;
- Do_Pgdn:
- mov BX,OFFSET W1
- call Close_Window
- mov AX,24
- mov [BX].rightrow,AX
- mov AX,79
- mov [BX].rightcol,AX
- ;
- mov AX,[BX].rightrow
- sub AX,[BX].height
- inc AX
- mov [BX].leftrow,AX
- ;
- mov AX,[BX].rightcol
- sub AX,[BX].xwidth
- inc AX
- mov [BX].leftcol,AX
- ;
- call Window_Parms ; recalculate parameters
- stc ; don't exit upon return
- ret
-
- ;
- ; Wait for any key pressed
- ;
- Get_Key:
- push BP ; just in case
- mov AH,00
- int 16h
- pop BP
- ret
-
- ;
- ; Calculate window parameters:
- ; 1) Physical starting address of window
- ; 2) Width of window in characters
- ; 3) Height of window
- ;
- ; Entry:
- ; BX = window pointer
- ; Exit:
- ; AX = Number of bytes contained in window
- ;
- Window_Parms:
- mov AX,[BX].leftrow
- mul BytesPL ; multiply by bytes per line
- mov CX,[BX].leftcol
- shl CX,1 ; times 2 for attribute byte
- add AX,CX
- mov SI,AX ; starting physical address of window
- mov [BX].startmem,AX ; save it for later
- ;
- ; Calculate size of window in bytes to allocate memory
- ;
- mov AX,[BX].rightcol
- inc AX
- sub AX,[BX].leftcol
- mov [BX].xwidth,AX
- mov CX,[BX].rightrow
- inc CX
- sub CX,[BX].leftrow
- mov [BX].height,CX
- mul CL ; AX = nbr of bytes of screen area
- shl AX,1 ; times 2 to get attributes also
- ret
-
- ;
- ; Table of function codes.
- ; (1st) word is DOS function code (AH),
- ; (2nd) word is pointer to string to display,
- ; (3rd) word is subroutine address to handle display of this type function.
- ;
- FCtbl:
- dw 0000h, STR00, Disp_Str
- dw 0100h, STR01, Disp_Str
- dw 0200h, STR02, Disp_02
- dw 0300h, STR03, Disp_03
- dw 0400h, STR04, Disp_04
- dw 0500h, STR05, Disp_05
- dw 0600h, STRUN, Disp_Str
- dw 0700h, STRUN, Disp_Str
- dw 0800h, STR08, Disp_Str
- dw 0900h, STR09, Disp_Str
- dw 0a00h, STR0a, Disp_0a
- dw 0b00h, STR0b, Disp_0b
- dw 0c00h, STR0c, Disp_0c
- dw 0d00h, STR0d, Disp_0d
- dw 0e00h, STRUN, Disp_Str
- dw 0f00h, STRUN, Disp_Str
- dw 1000h, STR10, Disp_10
- dw 1100h, STR11, Disp_11
- dw 1200h, STRUN, Disp_Str
- dw 1300h, STRUN, Disp_Str
- dw 1400h, STR14, Disp_Str
- dw 1500h, STR15, Disp_15
- dw 1600h, STR16, Disp_Str
- dw 1700h, STR17, Disp_17
- LENFC EQU $ - FCtbl
- ;
- ;
- STR00 db 'Reset Disk System'
- db 0
-
- STR01 db 'Get Disk Status'
- db 0
-
- STR02 db 'Read XX Disk Sector(s)'
- db 0
-
- STR03 db 'Write XX Disk Sector(s)'
- db 0
-
- STR04 db 'Verify XX Disk Sector(s)'
- db 0
-
- STR05 db 'Format Disk Track'
- db 0
-
- STR08 db 'Get Current Drive Parameters'
- db 0
-
- STR09 db 'Initialize Fixed-Disk Base Tables'
- db 0
-
- STR0a db 'Read Long'
- db 0
-
- STR0b db 'Write Long'
- db 0
-
- STR0c db 'Seek to Cylinder'
- db 0
-
- STR0d db 'Alternate Disk Reset'
- db 0
-
- STR10 db 'Test For Drive Ready'
- db 0
-
- STR11 db 'Recalibrate Drive'
- db 0
-
- STR14 db 'Controller Diagnostics'
- db 0
-
- STR15 db 'Get Disk Type'
- db 0
-
- STR16 db 'Change of Disk Status'
- db 0
-
- STR17 db 'Set Disk Type to XXH'
- db 0
-
- STR170 db 'No Disk'
- db 0
-
- STR171 db 'Regular Diskette'
- db 0
-
- STR173 db 'High Capacity Diskette (1.2 MB)'
- db 0
-
- STRUN db '** Undefined Function **'
- db 0
-
- ;
- ; Define format of WINDOW structure
- ;
- Window STRUC
- leftrow dw ?
- leftcol dw ?
- rightrow dw ?
- rightcol dw ?
- xwidth dw ?
- height dw ?
- startmem dw ?
- Window ENDS
-
- ;
- ; Allocate and initialize WINDOW parameters
- ;
- W1 Window <0, 42, 13, 79, 0, 0, 0>
-
- Winseg dw 0000 ; store segment of allocated memory
- ; for saving screen data
- Scrseg dw 0000 ; base segment for screen memory
- Pageseg dw 0000 ; segment after page offset factored in
- BytesPL dw 80*2 ; number of bytes per line (char + attr)
- Ret_Flg db 00 ; 'stop on return' flag
- SegEnv dw 0000 ; segment of environment
- SegPSP dw 0000 ; segment of PSP at load time
- SegEND dw 0000 ; program segment size
- Step_Flg db 00 ; step flag
- ; stop and display if bit 0 = 1
- ; terminate STEP13 if bit 1 = 1
- ;
- Skip_Typ db 00 ; type of function call to skip temporarily
- Skip_Flg db 00 ; set if function should be skipped
-
- Save13 dw ? ; save original Int13 vector here, IP
- dw ? ; and SEG
-
- Save28 dw ? ; save original Int28 vector here, IP
- dw ? ; and SEG
-
- Save1c dw ? ; save original Int1c vector here, IP
- dw ? ; and SEG
-
- Ssave LABEL DWORD
- SPsave dw ? ; save some of the user's registers here
- SSsave dw ? ; others will be on local stack
-
- AXsave dw ? ; these will have been left on user's
- DSsave dw ? ; stack instead of local stack
- CSsave dw ?
- IPsave dw ?
- FLsave dw ?
- Last_FC db ? ; save 'AH' as last function code
- ;
- INITmsg db CR
- db LF
- db '*** STEP13 Version 1.0 Installed ***'
- db CR
- db LF
- db LF
- db ' Press BOTH shift keys down to enable STEP13.'
- db CR
- db LF
- db ' Press CONTROL and BOTH shift keys down to remove STEP13 '
- db 'from memory.'
- db CR
- db LF
- db '$'
-
- ERRmsg db CR
- db LF
- db 'STEP13 already installed'
- db '$'
-
- FCStr db 'Int 13H - Function XXH'
- db 0
-
- DrvStr db 'Drive: XXH'
- db 0
-
- HedStr db 'Head: XX'
- db 0
-
- TrkStr db 'Track: XXX'
- db 0
-
- SecStr db 'Sector: XX'
- db 0
-
- CylStr db 'Cyl: XXX'
- db 0
-
- BufStr db 'Buffer Address = XXXX:XXXXH'
- db 0
-
- RCStr db 'Return Code = XXXXH'
- db 0
-
- CFStr db 'Carry Flag = X'
- db 0
-
- ZFStr db 'Zero Flag = X'
- db 0
-
- HlpStr1 db 'kip Current Func'
- db 0
-
- HlpStr2 db 'eturn Code'
- db 0
-
- HlpStr3 db ' - Non Stop'
- db 0
-
- HlpStr4 db ' - Move Window'
- db 0
-
- HlpStr5 db 'Press Any Key'
- db 0
-
- HlpStr6 db 'To Continue'
- db 0
-
- Astr db 32 dup (0) ; string for converting ASCII characters
-
- ;
- ; Local Program Stack Area
- ;
- db 128 dup (?)
- Pstack EQU $
-
-
- IF TESTING
- db 128 dup (?) ; Test Stack Area
- Tstack EQU $
-
- Buffer db 512 dup (?)
- ENDIF
-
-
- PRSIZE EQU $
-
- Code ENDS
-
- END Main
-